#ifndef _WX_APP_H_BASE_
#define _WX_APP_H_BASE_

#include "wx/event.h"
#include "wx/build.h"
#include "wx/init.h"
#include "wx/intl.h"

class wxAppConsole;
class wxAppTraits;
class wxCmdLineParser;
class wxLog;
class wxMessageOutput;

#if wxUSE_GUI
class wxEventLoop;
struct wxVideoMode;
#endif

typedef wxAppConsole* ( *wxAppInitializerFunction )();

enum {
  wxPRINT_WINDOWS = 1,
  wxPRINT_POSTSCRIPT = 2
};

class wxAppConsole : public wxEvtHandler {
  public:

    wxAppConsole();
    virtual ~wxAppConsole();
    virtual bool Initialize( int& argc, wxChar **argv );
    virtual bool CallOnInit() { return OnInit(); }
    virtual bool OnInit();
    virtual bool OnInitGui() { return true; }
    virtual int OnRun() = 0;
    virtual int OnExit();
    virtual void CleanUp();
    virtual void OnFatalException() { }
    virtual void Exit();
    wxString GetAppName() const {
      return m_appName.empty() ? m_className : m_appName;
    }
    void SetAppName( const wxString& name ) { m_appName = name; }
    wxString GetClassName() const { return m_className; }
    void SetClassName( const wxString& name ) { m_className = name; }
    const wxString& GetVendorName() const { return m_vendorName; }
    void SetVendorName( const wxString& name ) { m_vendorName = name; }

    #if wxUSE_CMDLINE_PARSER
    virtual void OnInitCmdLine( wxCmdLineParser& parser );
    virtual bool OnCmdLineParsed( wxCmdLineParser& parser );
    virtual bool OnCmdLineHelp( wxCmdLineParser& parser );
    virtual bool OnCmdLineError( wxCmdLineParser& parser );
    #endif

    wxAppTraits *GetTraits();
    virtual int FilterEvent( wxEvent& event );

    #if wxUSE_EXCEPTIONS
    virtual void HandleEvent( wxEvtHandler *handler,wxEventFunction func,wxEvent& event ) const;

    virtual void OnUnhandledException() { }
    #endif

    virtual void ProcessPendingEvents();
    virtual bool Yield( bool ( onlyIfNeeded ) = false ) { return true; }
    virtual void WakeUpIdle() { }
    static bool IsMainLoopRunning() { return false; }
    static void SetInitializerFunction( wxAppInitializerFunction fn ) { ms_appInitFn = fn; }
    static wxAppInitializerFunction GetInitializerFunction() { return ms_appInitFn; }
    static wxAppConsole *GetInstance() { return ms_appInstance; }
    static void SetInstance( wxAppConsole *app ) { ms_appInstance = app; }
    int      argc;
    wxChar **argv;

  protected:
    virtual wxAppTraits *CreateTraits();
    static wxAppInitializerFunction ms_appInitFn;
    static wxAppConsole *ms_appInstance;
    wxString m_vendorName,
             m_appName,
             m_className;
    wxAppTraits *m_traits;
    DECLARE_NO_COPY_CLASS( wxAppConsole )
};

#if wxUSE_GUI

class wxAppBase : public wxAppConsole {
  public:
    wxAppBase();
    virtual ~wxAppBase();
    virtual bool Initialize( int& argc, wxChar **argv );
    virtual bool OnInitGui();
    virtual int OnRun();
    int OnExit();
    virtual void CleanUp();
    static bool IsMainLoopRunning() {
      wxAppBase *app = wx_static_cast( wxAppBase *, GetInstance() );
      return app && app->m_mainLoop != NULL;
    }

    virtual int MainLoop();
    virtual void Exit();
    virtual void ExitMainLoop();
    virtual bool Pending();
    virtual bool Dispatch();
    virtual bool Yield( bool onlyIfNeeded = false ) = 0;
    virtual bool ProcessIdle();
    virtual bool SendIdleEvents( wxWindow* win, wxIdleEvent& event );

    #if wxUSE_EXCEPTIONS
    virtual bool OnExceptionInMainLoop();
    #endif

    virtual bool IsActive() const { return m_isActive; }
    void SetTopWindow( wxWindow *win ) { m_topWindow = win; }
    virtual wxWindow *GetTopWindow() const;
    void SetExitOnFrameDelete( bool flag ) { m_exitOnFrameDelete = flag ? Yes : No; }
    bool GetExitOnFrameDelete() const{ return m_exitOnFrameDelete == Yes; }
    virtual wxVideoMode GetDisplayMode() const;
    virtual bool SetDisplayMode( const wxVideoMode& ( info ) ) { return true; }
    void SetUseBestVisual( bool flag, bool forceTrueColour = false ) {
    m_useBestVisual = flag; m_forceTrueColour = forceTrueColour; }
    bool GetUseBestVisual() const { return m_useBestVisual; }
    virtual void SetPrintMode( int ( mode ) ) { }
    int GetPrintMode() const { return wxPRINT_POSTSCRIPT; }
    virtual wxLayoutDirection GetLayoutDirection() const;

    #if wxUSE_CMDLINE_PARSER
    virtual bool OnCmdLineParsed( wxCmdLineParser& parser );
    virtual void OnInitCmdLine( wxCmdLineParser& parser );
    #endif

    virtual void SetActive( bool isActive, wxWindow *lastFocus );
    wxDEPRECATED( bool Initialized() );
    void OnIdle( wxIdleEvent& event );
  protected:
    void DeletePendingObjects();
    virtual wxAppTraits *CreateTraits();
    wxEventLoop *m_mainLoop;
    wxWindow *m_topWindow;
    enum {
      Later = -1,
      No,
      Yes
    } m_exitOnFrameDelete;
    bool m_useBestVisual;
    bool m_forceTrueColour;
    bool m_isActive;
    DECLARE_NO_COPY_CLASS( wxAppBase )
};

inline bool wxAppBase::Initialized() { return true; }

#endif

#if wxUSE_GUI
#include "wx/gtk/app.h"
#else

typedef wxAppConsole wxApp;
#endif

#define wxTheApp wx_static_cast(wxApp*, wxApp::GetInstance())

extern void wxExit();

#ifndef wx_YIELD_DECLARED
#define wx_YIELD_DECLARED

extern bool wxYield();

#endif

extern void wxWakeUpIdle();

class wxAppInitializer {
  public:
    wxAppInitializer( wxAppInitializerFunction fn ) { wxApp::SetInitializerFunction( fn ); }
};

#define IMPLEMENT_WXWIN_MAIN_CONSOLE \
  int main(int argc, char **argv) { return wxEntry(argc, argv); }

#ifndef IMPLEMENT_WXWIN_MAIN
#define IMPLEMENT_WXWIN_MAIN IMPLEMENT_WXWIN_MAIN_CONSOLE
#endif

#ifdef __WXUNIVERSAL__
#include "wx/univ/theme.h"

#ifdef wxUNIV_DEFAULT_THEME
#define IMPLEMENT_WX_THEME_SUPPORT \
  WX_USE_THEME(wxUNIV_DEFAULT_THEME);
#else
#define IMPLEMENT_WX_THEME_SUPPORT
#endif
#else
#define IMPLEMENT_WX_THEME_SUPPORT
#endif

#define IMPLEMENT_APP_NO_MAIN(appname)                                      \
  wxAppConsole *wxCreateApp() {   \
    return new appname;                                                 \
  }                                                                       \
  wxAppInitializer                                                        \
  wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);        \
  DECLARE_APP(appname)                                                    \
  appname& wxGetApp() { return *wx_static_cast(appname*, wxApp::GetInstance()); }

#define IMPLEMENT_APP_NO_THEMES(appname)    \
  IMPLEMENT_APP_NO_MAIN(appname)          \
  IMPLEMENT_WXWIN_MAIN

#define IMPLEMENT_APP(appname)              \
  IMPLEMENT_APP_NO_THEMES(appname)        \
  IMPLEMENT_WX_THEME_SUPPORT


#define IMPLEMENT_APP_CONSOLE(appname)      \
  IMPLEMENT_APP_NO_MAIN(appname)          \
  IMPLEMENT_WXWIN_MAIN_CONSOLE

#define DECLARE_APP(appname) extern appname& wxGetApp();

extern wxAppConsole *wxCreateApp();
extern wxAppInitializer wxTheAppInitializer;

#endif
